perm filename ARITH.LSP[SCH,LSP] blob sn#688820 filedate 1982-11-14 generic text, type T, neo UTF8
;;; -*-LISP-*-

(HERALD ARITH "")

(eval-when (compile) (load "scm:umacro"))

;;; SCHEME generic arithmetic procedures

(DEFUN-IMPORT (+ ADD) N
  (IF (= N 0)
      0
      (DO ((I 2 (1+ I))
	   (ANS (ARG 1) (PLUS ANS (ARG I))))
	  ((> I N) (COERCE-DOWNWARD ANS)))))

(DEFUN-IMPORT (- SUB) N
  (COND ((= N 0) 0)
	((= N 1) (MINUS (ARG 1)))
	(T (DO ((I 2 (1+ I))
		(ANS (ARG 1) (DIFFERENCE ANS (ARG I))))
	       ((> I N) (COERCE-DOWNWARD ANS))))))

(DEFUN-IMPORT (* MUL) N
  (IF (= N 0)
      1
      (DO ((I 2 (1+ I))
	   (ANS (ARG 1) (TIMES ANS (ARG I))))
	  ((> I N) (COERCE-DOWNWARD ANS)))))

(DEFUN-IMPORT (// DIV) N
  (COND ((= N 0) 1)
	((= N 1) (COERCE-DOWNWARD (QUOTIENT 1 (FLOAT (ARG 1)))))
	(T (DO ((I 2 (1+ I))
		(ANS (ARG 1) (QUOTIENT ANS (FLOAT (ARG I)))))
	       ((> I N) (COERCE-DOWNWARD ANS))))))


(DEFUN-IMPORT (-1+ DEC) (X) (COERCE-DOWNWARD (SUB1 X)))

(DEFUN-IMPORT (1+ INC) (X) (COERCE-DOWNWARD (ADD1 X)))


(ADD-TO-LISP-IMPORTS
 '(ABS (ZERO? ZEROP) (NEGATIVE? MINUSP) (POSITIVE? PLUSP) (INTEGER? FIXP)))


;;; integer arithmetic

(DEFUN-IMPORT (QUOTIENT SCH-QUOTIENT) (X Y)
  (QUOTIENT X Y))

(DEFUN-IMPORT MOD (X Y)
  (IF (AND (FIXP X) (FIXP Y))
      (REMAINDER X Y)
      (COERCE-DOWNWARD (DIFFERENCE X (TIMES (SCH-QUOTIENT X Y) Y)))))

(DEFUN-IMPORT INTEGER-DIVIDE (X Y)
  (CONS (QUOTIENT X Y) (MOD X Y)))

(ADD-TO-LISP-IMPORTS '((REMAINDER MOD) GCD))


;;; Floating to integer arithmetic

(DEFUN-IMPORT TRUNCATE (X)
  (IF (MINUSP X)
      (IF (FIXP X)
	  X
	  (1+ (FIX X)))
      (FIX X)))  

(DEFUN-IMPORT CEILING (X)
  (IF (FIXP X)
      X
      (1+ (FIX X))))

(DEFUN-IMPORT ROUND (X)
  (FIX (PLUS X .5)))

(ADD-TO-LISP-IMPORTS '((FLOOR FIX)))

(DEFUN-IMPORT (EXPT SCHEXPT) (X Y)
  (COERCE-DOWNWARD
   (IF (MINUSP Y)
       (EXPT (FLOAT X) Y)
       (EXPT X Y))))


(DEFUN-IMPORT (EXP SCHEXP) (X) (COERCE-DOWNWARD (EXP X)))
(DEFUN-IMPORT (LOG SCHLOG) (X) (COERCE-DOWNWARD (LOG X)))

(DEFUN-IMPORT (SIN SCHSIN) (X) (COERCE-DOWNWARD (SIN X)))
(DEFUN-IMPORT (COS SCHCOS) (X) (COERCE-DOWNWARD (COS X)))
(DEFUN-IMPORT (TAN SCHTAN) (X) (COERCE-DOWNWARD (QUOTIENT (SIN X) (COS X))))
(DEFUN-IMPORT (ATAN SCHATAN) (Y X) (COERCE-DOWNWARD (ATAN Y X)))
(DEFUN-IMPORT (SQRT SCHSQRT) (X) (COERCE-DOWNWARD (SQRT X)))
(DEFUN-IMPORT (ASIN SCHASIN) (Y R) (COERCE-DOWNWARD (ATAN Y (OTHER-SIDE Y R))))
(DEFUN-IMPORT (ACOS SCHACOS) (X R) (COERCE-DOWNWARD (ATAN (OTHER-SIDE X R) X)))

(DEFUN OTHER-SIDE (Y R) (SQRT (SUB (MUL R R) (MUL Y Y))))


(DEFUN-IMPORT (MAX SCHMAX) N
  (IF (= N 0)
      (SCH-ERROR "Too few arguments to MAX" N)
      (DO ((I 2 (1+ I))
	   (ANS (ARG 1) (IF (GREATERP (ARG I) ANS) (ARG I) ANS)))
	  ((> I N) (COERCE-DOWNWARD ANS)))))

(DEFUN-IMPORT (MIN SCHMIN) N
  (IF (= N 0)
      (SCH-ERROR "Too few arguments to MIN" N)
      (DO ((I 2 (1+ I))
	   (ANS (ARG 1) (IF (LESSP (ARG I) ANS) (ARG I) ANS)))
	  ((> I N) (COERCE-DOWNWARD ANS)))))

(DEFUN-IMPORT (= EQUALTO?) N
  (IF (< N 2)
      (SCH-ERROR "Too few arguments to =" `(= . ,(listify n))))
  (IF (NOT (NUMBERP (ARG 1)))
      (SCH-ERROR "Non-numeric argument to =" (ARG 1)))
  (DO ((I 2 (1+ I)) (CURRENT (ARG 1)))
      ((> I N) 'T)
    (IF (NOT (NUMBERP (ARG I)))
	(SCH-ERROR "Non-numeric argument to =" (ARG I)))
    (COND ((AND (BIGP CURRENT) (BIGP (ARG I)))		; Both bignums, so
	   (IF (NOT (EQUAL CURRENT (ARG I))) (RETURN NIL))) ; only EQUAL works.
	  ((FLOATP CURRENT)				; Must compare as
	   (IF (NOT (= CURRENT (FLOAT (ARG I))))	;  flonums.
	       (RETURN NIL)))
	  ((FLOATP (ARG I))				; Similarly, compare as
	   (IF (NOT (= (FLOAT CURRENT) (ARG I)))	;  flonums,
	       (RETURN NIL))
	   (SETQ CURRENT (ARG I)))			;  but must set current
	  ((OR (BIGP CURRENT) (BIGP (ARG I)))		; fixnum < bignum,
	   (RETURN NIL))				;  so fail.
	  ((= CURRENT (ARG I)))				; Else, we have fixnums
	  (T (RETURN NIL)))))

(DEFUN-IMPORT (<> NOT-EQUALTO?) N
  (NOT (APPLY #'EQUALTO? (LISTIFY N))))

(DEFUN-IMPORT (>= SCH->=) N
  (IF (< N 2)
      (SCH-ERROR "Too few arguments to >=" `(= ,@(listify n))))
  (IF (NOT (NUMBERP (ARG 1)))
      (SCH-ERROR "Non-numeric argument to >=" (ARG 1)))
  (DO ((I 2 (1+ I)) (CURRENT (ARG 1) (ARG I)))
      ((> I N) 'T)
    (IF (NOT (NUMBERP (ARG I)))
	(SCH-ERROR "Non-numeric argument to >=" (ARG I)))
    (COND ((LESSP CURRENT (ARG I)) (RETURN NIL)))))

(DEFUN-IMPORT (<= SCH-<=) N
  (IF (< N 2)
      (SCH-ERROR "Too few arguments to <=" `(= ,@(listify n))))
  (IF (NOT (NUMBERP (ARG 1)))
      (SCH-ERROR "Non-numeric argument to <=" (ARG 1)))
  (DO ((I 2 (1+ I)) (CURRENT (ARG 1) (ARG I)))
      ((> I N) 'T)
    (IF (NOT (NUMBERP (ARG I)))
	(SCH-ERROR "Non-numeric argument to <=" (ARG I)))
    (COND ((GREATERP CURRENT (ARG I)) (RETURN NIL)))))


(ADD-TO-LISP-IMPORTS  '((< LESSP) (> GREATERP)))


(DEFUN-IMPORT EVEN? (X)
  (NOT (ODDP X)))

(ADD-TO-LISP-IMPORTS '((ODD? ODDP)))

(DEFUN-IMPORT (HASH SCH-HASH) (OBJECT INTEGER)
  (AND (NOT (FIXP INTEGER))
       (SCH-ERROR "Second argument must be an integer -- HASH" INTEGER))
  (REMAINDER (ABS (SXHASH OBJECT)) INTEGER))

(DEFUN-IMPORT RANDOMIZE (N)
  (COND ((NULL N)
	 (SSTATUS RANDOM
		  (APPLY #'* (APPEND (STATUS DATE) (STATUS DAYTIME)))))
	((FIXP N)
	 (SSTATUS RANDOM N))
	(T
	 (SCH-ERROR "Arg must be an integer or NIL -- RANDOMIZE" N))))

(ADD-TO-LISP-IMPORTS '(RANDOM))

(DEFUN-IMPORT (RUNTIME SCH-RUNTIME) ()
  (- (RUNTIME) (STATUS GCTIME)))